Skip to main content

OpenDSR API

Subsets implements the OpenDSR v2 specification as a Data Processor. Data Controllers can submit erasure requests through this API to exercise data subject rights under GDPR and CCPA.

Base URL: https://platform.subsets.com/api/opendsr

Authentication​

All endpoints require a valid Bearer token. Include it in the Authorization header:

Authorization: Bearer <token>

Two authentication methods are supported:

Use the OAuth 2.0 Client Credentials Grant to obtain a token. Subsets will provision a client_id and client_secret for your organization.

curl -X POST https://auth.subsets.ai/oauth/token \
-H "Content-Type: application/json" \
-d '{
"client_id": "<your_client_id>",
"client_secret": "<your_client_secret>",
"audience": "https://api.subsets.ai",
"grant_type": "client_credentials"
}'

The response contains an access_token to use as the Bearer token. Tokens are short-lived; request a new one when it expires.

Admin user token​

Users with admin role can also authenticate using the Bearer token obtained by SSO login.

Contact your Subsets account manager to obtain credentials.

Supported capabilities​

  • Request types: erasure only
  • Identity types: email (raw), controller_customer_id (raw)
  • Regulations: gdpr, ccpa

Endpoints​

Discovery​

Returns the capabilities of this OpenDSR processor.

GET https://platform.subsets.com/api/opendsr/discovery

Response 200

{
"api_version": "2.0",
"supported_identities": [
{ "identity_type": "email", "identity_format": "raw" },
{ "identity_type": "controller_customer_id", "identity_format": "raw" }
],
"supported_subject_request_types": ["erasure"]
}

Create request​

Submit a new data subject erasure request.

POST https://platform.subsets.com/api/opendsr/requests

Request body

FieldTypeRequiredDescription
regulationstringYes"gdpr" or "ccpa"
subject_request_idUUID v4YesUnique ID generated by the Controller
subject_request_typestringYesMust be "erasure"
submitted_timeRFC 3339YesTime of the original data subject request
subject_identitiesarrayNoArray of identity objects (see below)
status_callback_urlsarrayNonot yet supported
api_versionstringNoDesired API version ("2.0")

Identity object

FieldTypeRequiredDescription
identity_typestringYes"email" or "controller_customer_id"
identity_valuestringYesThe identity value
identity_formatstringYes"raw"

Example request

curl -X POST https://api.subsets.com/api/opendsr/requests \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"regulation": "gdpr",
"subject_request_id": "a7551968-d5d6-44b2-9831-815ac9017798",
"subject_request_type": "erasure",
"submitted_time": "2026-04-01T12:00:00Z",
"subject_identities": [
{
"identity_type": "email",
"identity_value": "johndoe@example.com",
"identity_format": "raw"
}
]
}'

Response 201

{
"controller_id": "d4f7a8b2-...",
"expected_completion_time": "2026-05-01T12:00:00Z",
"received_time": "2026-04-01T12:00:01Z",
"encoded_request": "<base64>",
"subject_request_id": "a7551968-d5d6-44b2-9831-815ac9017798",
"processor_signature": "not-yet-implemented"
}

Response headers: X-OpenDSR-Processor-Domain, X-OpenDSR-Signature

Error responses

StatusCondition
400Invalid request or unsupported subject_request_type
409A request with this subject_request_id already exists

Get request status​

Check the status of a previously submitted request.

GET https://platform.subsets.com/api/opendsr/requests/{subject_request_id}

Response 200

{
"controller_id": "d4f7a8b2-...",
"expected_completion_time": "2026-05-01T12:00:00Z",
"subject_request_id": "a7551968-d5d6-44b2-9831-815ac9017798",
"request_status": "pending",
"api_version": "2.0"
}

Possible statuses

StatusDescription
pendingRequest received, not yet started
in_progressRequest is being processed
completedRequest has been fulfilled
cancelledRequest was cancelled

Error responses

StatusCondition
404Request not found

Cancel request​

Cancel a pending erasure request. Only requests with pending status can be cancelled.

DELETE https://platform.subsets.com/api/opendsr/requests/{subject_request_id}

Response 202

{
"controller_id": "d4f7a8b2-...",
"received_time": "2026-04-02T10:00:00Z",
"subject_request_id": "a7551968-d5d6-44b2-9831-815ac9017798",
"processor_signature": "not-yet-implemented",
"api_version": "2.0"
}

Error responses

StatusCondition
400Request is not in pending status
404Request not found

Error format​

All error responses follow this structure:

{
"error": {
"code": 400,
"message": "Description of what went wrong"
}
}

Processing timeline​

Subsets aims to fulfill erasure requests within 30 days of submission. The expected_completion_time in the response reflects this timeline. You can poll the status endpoint to track progress.